package com.xhj.mybatis.type;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * TypeHandler
 *
 * @author XJks
 * @description 类型处理器接口，用于在 MyBatis 中处理 Java 类型与 JDBC 类型之间的转换。
 */
public interface TypeHandler<T> {
    /**
     * 设置参数的方法。用于将 Java 类型的参数设置到 PreparedStatement 中。
     *
     * @param ps        预编译的 SQL 语句对象（PreparedStatement）
     * @param i         参数在 SQL 语句中的位置（从 1 开始）
     * @param parameter 要设置的参数值（Java 类型）
     * @param jdbcType  参数对应的 JDBC 类型
     * @throws SQLException 如果设置参数时发生 SQL 异常
     */
    void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;

    /**
     * 从结果集中通过列名获取结果的方法。
     *
     * @param rs         查询结果集（ResultSet）
     * @param columnName 列名（当 useColumnLabel=false 时使用列名）
     * @return 返回转换后的 Java 类型结果
     * @throws SQLException 如果获取结果时发生 SQL 异常
     */
    T getResult(ResultSet rs, String columnName) throws SQLException;

    /**
     * 从结果集中通过列索引获取结果的方法。
     * TODO:
     *  相关说明:
     *    1.ResultSet 不是集合类型，而是一个“游标”对象，用于遍历数据库查询结果的每一行。它本质上是一个指向当前行的指针，每次调用 next() 方法，游标会移动到下一行。
     *    2.getResult(ResultSet rs, int columnIndex) 方法的作用是：在当前游标所指向的那一行，通过列索引（从1开始）获取该列的值，并将其转换为对应的 Java 类型对象。它只获取当前行的某一列的值，而不是所有行或所有列的值。
     *      举例说明：
     *        你执行了一个 SQL 查询，返回了多行多列的数据。
     *        ResultSet 让你可以用 while(rs.next()) 一行一行地遍历。
     *        在每一行里，你可以通过列索引（如1、2、3）或列名获取该行某一列的值。
     *        所以，getResult(rs, columnIndex) 只负责“当前行、指定列”的值的提取和类型转换。要获取所有行的数据，需要你自己遍历 ResultSet，每次调用该方法获取一列的值。
     *      总结：
     *        ResultSet 不是集合，而是行游标。
     *        getResult(rs, columnIndex) 只获取当前行的某一列的值。
     *        获取多行多列，需要遍历 ResultSet 并多次调用该方法。
     *
     * @param rs          查询结果集（ResultSet）
     * @param columnIndex 列索引（从 1 开始）
     * @return 返回转换后的 Java 类型结果
     * @throws SQLException 如果获取结果时发生 SQL 异常
     */
    T getResult(ResultSet rs, int columnIndex) throws SQLException;
}
